#include "EEExpMain.h"
#include "EEExpUtil.h"
#include "EEExpTree.h"
#include <fstream>
#include <iostream>
#include <iomanip>

#include <maya/MArgList.h>
#include <maya/MFileObject.h>
#include <maya/MItDag.h>
#include <maya/MDagPath.h>
#include <maya/MGlobal.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MItDependencyNodes.h>
#include <maya/MObject.h>
#include <maya/MObjectArray.h>
#include <maya/MStatus.h>
#include <maya/MString.h>
#include <maya/MStringArray.h>
#include <maya/MFnMesh.h>
#include <maya/MFloatPointArray.h>
#include <maya/MFloatVectorArray.h>
#include <maya/MFloatArray.h>
#include <maya/MIntArray.h>

#include <maya/MPxFileTranslator.h>

MStatus buildTriangleList(std::vector<triangle>* triangles, MFnMesh& mesh)
{
	int polyCount = 0;
	int indexCount = 0;
	int colorIndex = 0;
	int uvIndex = 0;

	MIntArray positionIndexArray;
	MIntArray trianglesPerPolygon;
	MIntArray trianglesVertexIndices;
	MIntArray UVIndexArray;

	MFloatArray Us;
	MFloatArray Vs;
	MFloatPointArray positions;
	MFloatVectorArray normals;
	MFloatVectorArray tangenets;
	MFloatVectorArray binormals;

	MVector position;
	MVector normal;
	MVector binormal;
	MVector tangent;

	mesh.getTriangles(trianglesPerPolygon,trianglesVertexIndices);
	mesh.getUVs(Us, Vs, NULL);
	mesh.getBinormals(binormals,MSpace::kWorld,	NULL);
	mesh.getNormals(normals,	MSpace::kWorld);
	mesh.getTangents(tangenets,	MSpace::kWorld,	NULL);
	mesh.getPoints(positions,	MSpace::kWorld);

	polyCount = trianglesPerPolygon.length();
	int triangleID = 0;
	for(int i = 0; i < polyCount; i++)
	{
		indexCount = trianglesPerPolygon[i];
		for(int j = 0; j < indexCount; j++)
		{
			int idxA = trianglesVertexIndices[triangleID + 0];
			int idxB = trianglesVertexIndices[triangleID + 1];
			int idxC = trianglesVertexIndices[triangleID + 2];

			triangleID += 3;

			//MVector vertexABinormal = binormals[vertexIndexA];
			//MVector vertexBBinormal = binormals[vertexIndexB];
			//MVector vertexCBinormal = binormals[vertexIndexC];

			//MVector normalABinormal = normals[vertexIndexA];
			//MVector normalBBinormal = normals[vertexIndexB];
			//MVector normalCBinormal = normals[vertexIndexC];

			//etc

			vertex vertexA = vertex(positions[idxA], Us[idxA], Vs[idxA]);
			vertex vertexB = vertex(positions[idxB], Us[idxB], Vs[idxB]);
			vertex vertexC = vertex(positions[idxC], Us[idxC], Vs[idxC]);
			
			triangle tri = triangle(vertexA,vertexB,vertexC);

			triangles->push_back(tri);
		}
	}

	return MStatus::kSuccess;
}

bool EEWorldExporter::writeKDTree(FILE* pFile)
{
	int leafCount = 0;

	if(WRITE_ASCII)
	{
		fprintf(pFile, "Writing tree structure:\n\n");
		fprintf(pFile, "Node count: %i\n",KDTree::treeNodes.size());
	}
	else
	{
		WRITESTRING("T", pFile);
		int nodeCount = (int)KDTree::treeNodes.size();
		fwrite(&nodeCount,sizeof(unsigned int),1,pFile);
	}

	for(unsigned int i = 0, j = (unsigned int)KDTree::treeNodes.size(); i < j; i++)
	{
		node* pNode = KDTree::treeNodes[i];

		if(pNode->isLeaf())
			leafCount++;

		pNode->writeTreeStructure(pFile);
	}

	
	if(WRITE_ASCII)
	{
		fprintf(pFile, "Writing geometry:\n\n");
		fprintf(pFile, "Leaf count: %i\n",leafCount);
	}
	else
	{
		WRITESTRING("G", pFile);
		fwrite(&leafCount,sizeof(unsigned int),1,pFile);
	}

	for(unsigned int i = 0, j = (unsigned int)KDTree::treeNodes.size(); i < j; i++)
	{
		node* pNode = KDTree::treeNodes[i];

		if(pNode->isLeaf())
			pNode->writeLeafData(pFile);
	}
	return true;
}

MStatus	EEWorldExporter::writeData(FILE* pFile)
{
	MStatus stat;
	MItDag itDag(MItDag::kDepthFirst, MFn::kMesh, &stat);

	if(stat == MStatus::kFailure)
	{
		MGlobal::displayError("Could not itterate scene");
		return MStatus::kFailure;
	}

	std::vector<triangle>* worldTriangles = new std::vector<triangle>();

	std::cout << std::endl<< std::endl<< std::endl<< std::endl<< std::endl<< std::endl<< std::endl
		<< std::endl<< std::endl<< std::endl<< std::endl<< std::endl<< std::endl;

	// loop through all nodes
	for( ; !itDag.isDone(); itDag.next() )
	{
		MDagPath dagPath;
		if(itDag.getPath(dagPath) == MStatus::kFailure)
		{	
			MGlobal::displayError("Could not itterate scene");
			return MStatus::kFailure;
		}

		MFnMesh mesh = MFnMesh(dagPath,&stat);

		//if mesh is a world mesh
		if(buildTriangleList(worldTriangles, mesh) == MStatus::kFailure)
		{	
			MGlobal::displayError("Could not assemble world triangle list");
			return MStatus::kFailure;
		}
	}

	node* pRoot = new node();
	KDTree::partionTriangles(plane(), worldTriangles, Axis::X, pRoot);

	writeKDTree(pFile);


	KDTree::depth = 0;
	KDTree::nodecount = 0;
	KDTree::treeNodes.clear();
	node::nextNodeID = 0;

	return MStatus::kSuccess;
}